﻿// ******************************************************
// Copyright © 2010 DCOM Productions®, 
// All Rights Reserved
// ******************************************************

namespace BitFlex.EnterpriseServices.WindowsShell {
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Win32;
    using System.Diagnostics;

    /// <summary>
    /// Base class to implement an Explorer Policy
    /// </summary>
    public abstract class ExplorerPolicyBase : IWinlogonPolicy {
        /// <summary>
        /// Initializes a new instance of the BitFlex.EnterpriseServices.WindowsShell.ExplorerPolicyBase class
        /// </summary>
        /// <param name="name"></param>
        public ExplorerPolicyBase(string name) {
            m_Name = name;
        }

        #region IWinlogonPolicy Members

        /// <summary>
        /// Gets a System.Boolean value indicating whether this policy is currently enforced in the system
        /// </summary>
        public bool Enforced {
            get {
                RegistryKey key = null;
                try {
                    if (Logon == Winlogon.CurrentUser)
                        key = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", true);
                    else if (Logon == Winlogon.LocalMachine)
                        key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", true);
                    string[] names = key.GetValueNames();
                    if (names.Contains(Name)) {
                        object value = key.GetValue(Name);
                        int dword = (int)value;
                        if (dword == 1)
                            return true;
                        else
                            return false;
                    }
                    else
                        return false;
                }
                catch (System.Exception ex) {
                    Debug.Assert(false, ex.ToString());
                    return false;
                }
                finally {
                    if (key != null) {
                        key.Close();
                    }
                }
            }
        }

        private Winlogon m_Logon = Winlogon.LocalMachine;
        /// <summary>
        /// Gets or sets the Winlogon that this policy will apply to
        /// </summary>
        public Winlogon Logon {
            get {
                return m_Logon;
            }
            set {
                m_Logon = value;
            }
        }

        private string m_Name = string.Empty;
        /// <summary>
        /// Gets the name of the policy
        /// </summary>
        public string Name {
            get {
                return m_Name;
            }
        }

        /// <summary>
        /// Applies the policy to the system
        /// </summary>
        public void Apply() {
            RegistryKey key = null;
            try {
                if (Logon == Winlogon.CurrentUser) {
                    key = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", true);
                    if (key == null) {
                        key = Registry.CurrentUser.CreateSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer");
                    }
                }
                else if (Logon == Winlogon.LocalMachine) {
                    key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", true);
                    if (key == null) {
                        key = Registry.LocalMachine.CreateSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer");
                    }
                }
                key.SetValue(Name, 1, RegistryValueKind.DWord);
            }
            catch (System.ArgumentException ex) {
                throw new PolicyAccessException(ex);
            }
            catch (System.Security.SecurityException ex) {
                throw new PolicyAccessException(ex);
            }
            catch (System.ObjectDisposedException ex) {
                throw new PolicyAccessException(ex);
            }
            catch (System.UnauthorizedAccessException ex) {
                throw new PolicyAccessException(ex);
            }
            catch (System.IO.IOException ex) {
                throw new PolicyAccessException(ex);
            }
            finally {
                if (key != null) {
                    key.Close();
                }
            }
        }

        /// <summary>
        /// Removes the policy from the system
        /// </summary>
        public void Remove() {
            RegistryKey key = null;
            try {
                if (Logon == Winlogon.CurrentUser) {
                    key = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", true);
                }
                else if (Logon == Winlogon.LocalMachine) {
                    key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", true);
                }
                if (key != null) {
                    key.DeleteValue(Name, true);
                }
            }
            catch (System.ArgumentException) {
                // Here there is no reason to raise an exception
                // If the policy does not exist, it's not enforced anyway
                return;
            }
            catch (System.Security.SecurityException ex) {
                throw new PolicyAccessException(ex);
            }
            catch (System.ObjectDisposedException ex) {
                throw new PolicyAccessException(ex);
            }
            catch (System.UnauthorizedAccessException ex) {
                throw new PolicyAccessException(ex);
            }
            finally {
                if (key != null) {
                    key.Close();
                }
            }
        }

        #endregion
    }
}
